package com.liulishuo.demo.filedownloaderapplication;


import com.liulishuo.filedownloader.BaseDownloadTask;
import com.liulishuo.filedownloader.FileDownloadListener;
import com.liulishuo.filedownloader.FileDownloadQueueSet;
import com.liulishuo.filedownloader.FileDownloader;
import com.liulishuo.filedownloader.util.FileDownloadUtils;
import com.oszc.bbhmlibrary.utils.MainHandler;
import com.oszc.bbhmlibrary.utils.ResUtil;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.*;
import ohos.agp.window.dialog.ToastDialog;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class MultiTaskTestAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        setUIContent(ResourceTable.Layout_layout_multi_task);
        assignViews();
        resetDisplayData();

        actionBtn.setTag(true);
        actionBtn.setClickedListener((view) -> {
            final boolean toStart = (boolean) actionBtn.getTag();
            if (toStart) {
                if (start()) {
                    actionBtn.setText(ResourceTable.String_pause);
                    actionBtn.setTag(false);
                }
            } else {
                actionBtn.setText(ResourceTable.String_start);
                pause();
                actionBtn.setTag(true);
            }
        });

        taskCountSb.setMaxValue(Constant.URLS.length);
        taskCountSb.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int progress, boolean b) {
                taskCountTv.setText(String.valueOf(progress));
            }

            @Override
            public void onTouchStart(Slider slider) {

            }

            @Override
            public void onTouchEnd(Slider slider) {

            }
        });

        deleteAllFileBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                int count = 0;
                File file = new File(FileDownloadUtils.getDefaultSaveRootPath());
                do {
                    if (!file.exists()) {
                        break;
                    }

                    if (!file.isDirectory()) {
                        break;
                    }

                    File[] files = file.listFiles();

                    if (files == null) {
                        break;
                    }

                    for (File file1 : files) {
                        count++;
                        file1.delete();
                    }

                } while (false);
                new ToastDialog(getContext()).setText(String.format("Complete delete %d files", count)).show();
            }
        });

        avoidMissFrameCb.setChecked(FileDownloader.isEnabledAvoidDropFrame());
        avoidMissFrameCb.setCheckedStateChangedListener(new AbsButton.CheckedStateChangedListener() {
            @Override
            public void onCheckedChanged(AbsButton absButton, boolean isChecked) {
                if (isChecked) {
                    FileDownloader.enableAvoidDropFrame();
                } else {
                    FileDownloader.disableAvoidDropFrame();
                }
            }
        });
    }

    private void resetDisplayData() {
        pendingPb.setProgressValue(0);
        connectedPb.setProgressValue(0);
        progressPb.setProgressValue(0);
        retryPb.setProgressValue(0);
        errorPb.setProgressValue(0);
        pausedPb.setProgressValue(0);
        completedReusedPb.setProgressValue(0);
        completedDownloadingPb.setProgressValue(0);
        warnPb.setProgressValue(0);
        overTaskPb.setProgressValue(0);
        pendingTv.setText(ResourceTable.String_multitask_test_pending);
        connectedTv.setText(ResourceTable.String_multitask_test_connected);
        progressTv.setText(ResourceTable.String_multitask_test_progress);
        retryTv.setText(ResourceTable.String_multitask_test_retry);
        errorTv.setText(ResourceTable.String_multitask_test_error);
        pausedTv.setText(ResourceTable.String_multitask_test_paused);
        completedReusedTv.setText(ResourceTable.String_multitask_test_completed_reused);
        completedDownloadingTv.setText(ResourceTable.String_multitask_test_completed_downloading);
        warnTv.setText(ResourceTable.String_multitask_test_warn);
        pendingInfoTv.setText("");
        connectedInfoTv.setText("");
        retryInfoTv.setText("");
        progressInfoTv.setText("");
        errorInfoTv.setText("");
        pausedInfoTv.setText("");
        completedReusedInfoTv.setText("");
        completedDownloadingInfoTv.setText("");
        warnInfoTv.setText("");
    }

    private long start = 0;

    private boolean start() {
        final int count = Integer.valueOf(taskCountTv.getText().toString());
        if (count <= 0) {
            return false;
        }

        taskCountSb.setEnabled(false);
        pendingPb.setMaxValue(count);
        connectedPb.setMaxValue(count);
        progressPb.setMaxValue(count);
        retryPb.setMaxValue(count);
        errorPb.setMaxValue(count);
        pausedPb.setMaxValue(count);
        completedReusedPb.setMaxValue(count);
        completedDownloadingPb.setMaxValue(count);
        warnPb.setMaxValue(count);
        overTaskPb.setMaxValue(count);
        resetDisplayData();

        // 需要时再显示
        retryInfoTv.setVisibility(Component.HIDE);
        retryPb.setVisibility(Component.HIDE);
        retryTv.setVisibility(Component.HIDE);

        isStopTimer = false;
        timeConsumeTv.setTag(0);
        goTimeCount();
        start = System.currentTimeMillis();
        // =================== How to Download tasks: =============================
        downloadListener = createLis();
//        The first way-----------------------------:
//        for (int i = 0; i < count; i++) {
//            final String url = Constant.URLS[i];
//            FileDownloader.getImpl().create(url)
//                    .setListener(downloadListener)
//                    .setAutoRetryTimes(1)
//                    .setTag(i + 1)
//                    .setCallbackProgressTimes(0)
//                    .asInQueueTask()
//                    .enqueue();
//        }
//        FileDownloader.getImpl().start(downloadListener, serialRbtn.isChecked());

//        The second way----------------------------:

        final FileDownloadQueueSet queueSet = new FileDownloadQueueSet(downloadListener);

        final List<BaseDownloadTask> tasks = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            tasks.add(FileDownloader.getImpl().create(Constant.URLS[i]).setTag(i + 1));
        }
        queueSet.disableCallbackProgressTimes(); // do not want each task's download progress's callback,
        // we just consider which task will completed.

        // auto retry 1 time if download fail
        queueSet.setAutoRetryTimes(1);

        if (serialRbtn.isChecked()) {
            // start download in serial order
            queueSet.downloadSequentially(tasks);
            // if your tasks are not a list, invoke such following will more readable:
//            queueSet.downloadSequentially(
//                    FileDownloader.getImpl().create(url).setPath(...),
//                    FileDownloader.getImpl().create(url).addHeader(...,...),
//                    FileDownloader.getImpl().create(url).setPath(...)
//            );
        } else {
            // start parallel download
            queueSet.downloadTogether(tasks);
            // if your tasks are not a list, invoke such following will more readable:
//            queueSet.downloadTogether(
//                    FileDownloader.getImpl().create(url).setPath(...),
//                    FileDownloader.getImpl().create(url).setPath(...),
//                    FileDownloader.getImpl().create(url).setSyncCallback(true)
//            );
        }
        queueSet.start();

        return true;
    }

    private FileDownloadListener downloadListener;

    private void pause() {
        FileDownloader.getImpl().pause(downloadListener);
        stopTimeCount();
        taskCountSb.setEnabled(true);
    }

    private void stopTimeCount() {

        if (isTerminating()) {
            return;
        }

        isStopTimer = true;
        MainHandler.removeTask(timeCountRunnable);
        final long consume = System.currentTimeMillis() - start;
        if (timeConsumeTv != null) {
            timeConsumeTv.setText(String.valueOf(consume / 1000f));
        }
    }

    private FileDownloadListener createLis() {
        return new FileDownloadListener() {

            @Override
            protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                // 之所以加这句判断，是因为有些异步任务在pause以后，会持续回调pause回来，而有些任务在pause之前已经完成，
                // 但是通知消息还在线程池中还未回调回来，这里可以优化
                // 后面所有在回调中加这句都是这个原因
                if (task.getListener() != downloadListener) {
                    return;
                }
                pendingPb.setProgressValue(pendingPb.getProgress() + 1);
                pendingTv.setText(String.format(ResUtil.getString(getContext(), ResourceTable.String_multitask_test_pending), pendingPb.getProgress()));
                pendingInfoTv.append((int) task.getTag() + " | ");
            }

            @Override
            protected void connected(BaseDownloadTask task, String etag, boolean isContinue,
                                     int soFarBytes, int totalBytes) {

                super.connected(task, etag, isContinue, soFarBytes, totalBytes);
                if (task.getListener() != downloadListener) {
                    return;
                }

                connectedPb.setProgressValue(connectedPb.getProgress() + 1);
                connectedTv.setText(String.format(ResUtil.getString(getContext(), ResourceTable.String_multitask_test_connected),
                        connectedPb.getProgress()));

                connectedInfoTv.append((int) task.getTag() + " | ");
            }

            @Override
            protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                if (task.getListener() != downloadListener) {
                    return;
                }
//                progressPb.setProgressValue(progressPb.getProgress() + 1);
//                progressTv.setText("progress: " + progressPb.getProgress());
//                progressInfoTv.append((int)task.getTag() + " | ");
            }

            @Override
            protected void blockComplete(BaseDownloadTask task) {
                if (task.getListener() != downloadListener) {
                    return;
                }
            }

            @Override
            protected void retry(BaseDownloadTask task, Throwable ex, int retryingTimes, int soFarBytes) {
                super.retry(task, ex, retryingTimes, soFarBytes);
                if (task.getListener() != downloadListener) {
                    return;
                }

                retryInfoTv.setVisibility(Component.HIDE);
                retryPb.setVisibility(Component.HIDE);
                retryTv.setVisibility(Component.HIDE);

                retryPb.setProgressValue(retryPb.getProgress() + 1);
                retryTv.setText(String.format(ResUtil.getString(getContext(), ResourceTable.String_multitask_test_retry), retryPb.getProgress()));
                retryInfoTv.append((int) task.getTag() + " | ");
            }

            @Override
            protected void completed(BaseDownloadTask task) {
                if (task.getListener() != downloadListener) {
                    return;
                }

                if (task.isReusedOldFile()) {
                    completedReusedPb.setProgressValue(completedReusedPb.getProgress() + 1);
                    completedReusedTv.setText(String.format(ResUtil.getString(getContext(), ResourceTable.String_multitask_test_completed_reused),
                            completedReusedPb.getProgress()));
                    completedReusedInfoTv.append((int) task.getTag() + " | ");
                } else {
                    completedDownloadingPb.setProgressValue(completedDownloadingPb.getProgress() + 1);
                    completedDownloadingTv.
                            setText(String.format(ResUtil.getString(getContext(), ResourceTable.String_multitask_test_completed_downloading),
                                    completedDownloadingPb.getProgress()));

                    completedDownloadingInfoTv.append((int) task.getTag() + " | ");
                }

                overTaskPb.setProgressValue(overTaskPb.getProgress() + 1);
                checkEndAll();
            }

            @Override
            protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                if (task.getListener() != downloadListener) {
                    return;
                }
                pausedPb.setProgressValue(pausedPb.getProgress() + 1);
                pausedTv.setText(String.format(ResUtil.getString(getContext(), ResourceTable.String_multitask_test_paused), pausedPb.getProgress()));
                pausedInfoTv.append((int) task.getTag() + " | ");
                overTaskPb.setProgressValue(overTaskPb.getProgress() + 1);
            }

            @Override
            protected void error(BaseDownloadTask task, Throwable e) {
                if (task.getListener() != downloadListener) {
                    return;
                }
                errorPb.setProgressValue(errorPb.getProgress() + 1);
                errorTv.setText(String.format(ResUtil.getString(getContext(), ResourceTable.String_multitask_test_error), errorPb.getProgress()));
                errorInfoTv.append((int) task.getTag() + " | ");
                overTaskPb.setProgressValue(overTaskPb.getProgress() + 1);
                checkEndAll();
            }

            @Override
            protected void warn(BaseDownloadTask task) {
                if (task.getListener() != downloadListener) {
                    return;
                }

                warnPb.setProgressValue(warnPb.getProgress() + 1);
                warnTv.setText(String.format(ResUtil.getString(getContext(), ResourceTable.String_multitask_test_warn), warnPb.getProgress()));
                warnInfoTv.append((int) task.getTag() + " | ");
                overTaskPb.setProgressValue(overTaskPb.getProgress() + 1);
                checkEndAll();
            }
        };
    }

    private void checkEndAll() {
        final boolean isEndAll = overTaskPb.getProgress() >= Integer.valueOf(taskCountTv.getText().toString());
        if (isEndAll) {

            /*

                    GlobalMonitor.getImpl().getMarkOver()));

             */

            stopTimeCount();
            actionBtn.setTag(true);
            actionBtn.setText("Start");
            taskCountSb.setEnabled(true);
        }
    }

    private boolean isStopTimer = true;

    private void goTimeCount() {
        if (isTerminating()) {
            return;
        }
        final int time = (int) timeConsumeTv.getTag();
        timeConsumeTv.setText(String.valueOf(time));
        MainHandler.postDelay(timeCountRunnable, 1000);
        //timeConsumeTv.getHandler().postDelayed(timeCountRunnable, 1000);
    }

    private Runnable timeCountRunnable = new Runnable() {
        @Override
        public void run() {
            if (isStopTimer) {
                return;
            }
            timeConsumeTv.setTag((int) timeConsumeTv.getTag() + 1);
            goTimeCount();
        }
    };

    private Slider taskCountSb;
    private Text taskCountTv;
    private Text timeConsumeTv;
    private RadioContainer wayRgp;
    private RadioButton serialRbtn;
    private RadioButton parallelRbtn;
    private Checkbox avoidMissFrameCb;
    private ProgressBar overTaskPb;
    private Button actionBtn;
    private Text pendingTv;
    private Text pendingInfoTv;
    private ProgressBar pendingPb;
    private Text connectedTv;
    private Text connectedInfoTv;
    private ProgressBar connectedPb;
    private Text progressTv;
    private Text progressInfoTv;
    private ProgressBar progressPb;
    private Text retryTv;
    private Text retryInfoTv;
    private ProgressBar retryPb;
    private Text errorTv;
    private Text errorInfoTv;
    private ProgressBar errorPb;
    private Text pausedTv;
    private Text pausedInfoTv;
    private ProgressBar pausedPb;
    private Text completedReusedTv;
    private Text completedReusedInfoTv;
    private ProgressBar completedReusedPb;
    private Text completedDownloadingTv;
    private Text completedDownloadingInfoTv;
    private ProgressBar completedDownloadingPb;
    private Text warnTv;
    private Text warnInfoTv;
    private ProgressBar warnPb;
    private Button deleteAllFileBtn;

    private void assignViews() {
        taskCountSb = (Slider) findComponentById(ResourceTable.Id_task_count_sb);
        taskCountTv = (Text) findComponentById(ResourceTable.Id_task_count_tv);
        timeConsumeTv = (Text) findComponentById(ResourceTable.Id_time_consume_tv);
        wayRgp = (RadioContainer) findComponentById(ResourceTable.Id_way_rgp);
        serialRbtn = (RadioButton) findComponentById(ResourceTable.Id_serial_rbtn);
        parallelRbtn = (RadioButton) findComponentById(ResourceTable.Id_parallel_rbtn);
        avoidMissFrameCb = (Checkbox) findComponentById(ResourceTable.Id_avoid_miss_frame_cb);
        overTaskPb = (ProgressBar) findComponentById(ResourceTable.Id_over_task_pb);
        actionBtn = (Button) findComponentById(ResourceTable.Id_action_btn);
        pendingTv = (Text) findComponentById(ResourceTable.Id_pending_tv);
        pendingInfoTv = (Text) findComponentById(ResourceTable.Id_pending_info_tv);
        pendingPb = (ProgressBar) findComponentById(ResourceTable.Id_pending_pb);
        connectedTv = (Text) findComponentById(ResourceTable.Id_connected_tv);
        connectedInfoTv = (Text) findComponentById(ResourceTable.Id_connected_info_tv);
        connectedPb = (ProgressBar) findComponentById(ResourceTable.Id_connected_pb);
        progressTv = (Text) findComponentById(ResourceTable.Id_progress_tv);
        progressInfoTv = (Text) findComponentById(ResourceTable.Id_progress_info_tv);
        progressPb = (ProgressBar) findComponentById(ResourceTable.Id_progress_pb);
        retryTv = (Text) findComponentById(ResourceTable.Id_retry_tv);
        retryInfoTv = (Text) findComponentById(ResourceTable.Id_retry_info_tv);
        retryPb = (ProgressBar) findComponentById(ResourceTable.Id_retry_pb);
        errorTv = (Text) findComponentById(ResourceTable.Id_error_tv);
        errorInfoTv = (Text) findComponentById(ResourceTable.Id_error_info_tv);
        errorPb = (ProgressBar) findComponentById(ResourceTable.Id_error_pb);
        pausedTv = (Text) findComponentById(ResourceTable.Id_paused_tv);
        pausedInfoTv = (Text) findComponentById(ResourceTable.Id_paused_info_tv);
        pausedPb = (ProgressBar) findComponentById(ResourceTable.Id_paused_pb);
        completedReusedTv = (Text) findComponentById(ResourceTable.Id_completed_with_old_tv);
        completedReusedInfoTv = (Text) findComponentById(ResourceTable.Id_completed_with_old_info_tv);
        completedReusedPb = (ProgressBar) findComponentById(ResourceTable.Id_completed_with_old_pb);
        completedDownloadingTv = (Text) findComponentById(ResourceTable.Id_completed_tv);
        completedDownloadingInfoTv = (Text) findComponentById(ResourceTable.Id_completed_info_tv);
        completedDownloadingPb = (ProgressBar) findComponentById(ResourceTable.Id_completed_pb);
        warnTv = (Text) findComponentById(ResourceTable.Id_warn_tv);
        warnInfoTv = (Text) findComponentById(ResourceTable.Id_warn_info_tv);
        warnPb = (ProgressBar) findComponentById(ResourceTable.Id_warn_pb);
        deleteAllFileBtn = (Button) findComponentById(ResourceTable.Id_delete_all_file_btn);
    }

}